package com.manage.generator.service;

import com.manage.common.exception.ServiceException;
import com.manage.common.utils.StringUtils;
import com.manage.generator.domain.GenParams;
import com.manage.generator.domain.GenTemplate;
import com.manage.generator.mapper.GenTemplateMapper;
import org.apache.commons.io.IOUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


/**
 * @description: 代码生成实现类
 * @author: 喵师傅
 * @date: 2024/2/7 14:56
 */
@Service
public class GenTemplateServiceImpl implements GenTemplateService {

    public final GenTemplateMapper templateMapper;

    @Autowired
    public GenTemplateServiceImpl(GenTemplateMapper genTemplateMapper) {
        this.templateMapper = genTemplateMapper;
    }

    /**
     * 条件查询所有模板
     *
     * @param codeTemplate 查询参数
     * @return 查询结果
     */
    @Override
    public List<GenTemplate> selectTemplateList(GenTemplate codeTemplate) {
        List<GenTemplate> result = templateMapper.selectTemplateList(codeTemplate);
        if (!CollectionUtils.isEmpty(result)) {
            for (GenTemplate template : result) {
                if (!CollectionUtils.isEmpty(template.getParamsList())) {
                    template.setParamsList(GenParams.paramsListToTree(template.getParamsList()));
                }
            }
        }
        return result;
    }

    /**
     * 保存模板
     *
     * @param po 实体
     */
    @Override
    public int insertTemplate(GenTemplate po) {
        return templateMapper.insertTemplate(po);
    }

    /**
     * 编辑
     *
     * @param po 实体
     */
    @Override
    public int updateTemplate(GenTemplate po) {
        return templateMapper.updateTemplate(po);
    }

    /**
     * 删除
     *
     * @param id 要删除的id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteTemplateById(Long id) {
        // 清空模板关联的参数
        templateMapper.clearTemplateParams(id);
        return templateMapper.deleteTemplateById(id);
    }

    /**
     * 保存模板参数
     *
     * @param template 模板
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int saveTemplateParams(GenTemplate template) {
        // 清空模板关联的参数
        templateMapper.clearTemplateParams(template.getId());
        int saveCount = 0;
        if (!CollectionUtils.isEmpty(template.getParamsList())) {
            for (GenParams templateParams : template.getParamsList()) {
                templateParams.setTemplateId(template.getId());
                templateMapper.insertTemplateParams(templateParams);
                saveCount++;
            }
        }
        return saveCount;
    }

    /**
     * 预览代码
     *
     * @param templateList 模板集合
     * @return 代码生成结果
     */
    @Override
    public Map<String, String> previewCode(List<GenTemplate> templateList) {
        Map<String, String> result = new LinkedHashMap<>();
        try {
            Velocity.init();
            if (!CollectionUtils.isEmpty(templateList)) {
                for (GenTemplate codeTemplate : templateList) {
                    // 解析模板生成代码
                    String codeStr = generateCode(codeTemplate);
                    result.put(codeTemplate.getName() + "." + codeTemplate.getCatalog(), codeStr);
                }
            }
        } catch (Exception e) {
            throw new ServiceException("模板文件解析异常");
        }
        return result;
    }

    /**
     * 解析模板生成代码
     *
     * @param codeTemplate 模板
     * @return 生成结果
     */
    private String generateCode(GenTemplate codeTemplate) {
        // 当前模板的参数
        Map<String, Object> paramsMap = GenParams.paramsListToMap(codeTemplate.getParamsList());

        VelocityContext context = new VelocityContext(paramsMap);
        // 解析模板
        StringWriter stringWriter = new StringWriter();
        Velocity.evaluate(context, stringWriter, "generateCode", codeTemplate.getTemplateStr());
        return stringWriter.toString();
    }

    /**
     * 生成代码(压缩包)
     *
     * @param templateList 模板集合
     * @return 代码生成结果
     */
    @Override
    public byte[] generateCodeFile(List<GenTemplate> templateList) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        // 调用预览代码逻辑
        Map<String, String> templateRender = previewCode(templateList);

        try {
            for (Map.Entry<String, String> entry : templateRender.entrySet()) {
                // 渲染模板
                StringWriter sw = new StringWriter();
                sw.write(entry.getValue());
                // 文件路径
                String filePath = entry.getKey();
                // 添加到zip
                zip.putNextEntry(new ZipEntry(filePath));
                IOUtils.write(sw.toString(), zip, StandardCharsets.UTF_8);
                IOUtils.closeQuietly(sw);
                zip.flush();
                zip.closeEntry();
            }
        } catch (IOException e) {
            throw new ServiceException("代码生成异常：" + e.getMessage());
        }
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    /**
     * 校验模板名称是否唯一
     *
     * @param po 模板
     * @return 查询结果
     */
    @Override
    public boolean checkTemplateNameUnique(GenTemplate po) {
        long templateId = StringUtils.isNull(po.getId()) ? -1L : po.getId();
        GenTemplate info = templateMapper.checkTemplateNameUnique(po.getName());
        return !StringUtils.isNotNull(info) || info.getId() == templateId;
    }
}
